;; The first three lines of this file were inserted by DrRacket. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "htdp-beginner-abbr-reader.ss" "lang")((modname u2-huebung) (read-case-sensitive #t) (teachpacks ()) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ())))
;; concern defines the rating of a single area of interest
;; topic: string - the area of interest
;; value: number - the rating {-2; -1; 0; 1; 2}
(define-struct concern (topic value))


;; person defines a person and the interests
;; name: symbol - the person's name
;; concerns: (listof concern) - the person's areas of interest
(define-struct person (name concerns))


;; person-similarity defines the overall similarity value of
;; a person to Indiana Jones
;; name: symbol - the person's name
;; similarity: number - the accumulated sum of interest comparison values
(define-struct person-similarity (name similarity))


;; Allan Quatermain (by Henry Rider Haggard)
(define Quatermain (make-person 'AllanQuatermain (list
                                                  (make-concern "Hunting" 2)
                                                  (make-concern "Adventures" 2)
                                                  (make-concern "Ignoring the law" -2)
                                                  (make-concern "Occult things and rituals" -1)
                                                  (make-concern "Science" -1))))

;; Tom Sawyer (by Mark Twain)
(define Sawyer (make-person 'TomSawyer (list
                                        (make-concern "Treasure hunts" 1)
                                        (make-concern "Adventures" 2)
                                        (make-concern "Ignoring the law" 2)
                                        (make-concern "Science" -2))))

;; Mina Harker (by Bram Stoker)
(define Harker (make-person 'MinaHarker (list
                                         (make-concern "Adventures" -1)
                                         (make-concern "Occult things and rituals" 2)
                                         (make-concern "Keeping personal things secret" 2))))

;; Dorian Gray (by Oscar Wilde)
(define Gray (make-person 'DorianGray (list
                                       (make-concern "Ignoring the law" 1)
                                       (make-concern "Occult things and rituals" 2)
                                       (make-concern "Keeping personal things secret" 2))))

;; Henry Jekyll/Edward Hyde (by Robert Lewis Stevenson)
(define Jekyll (make-person 'HenryJeckyll (list
                                           (make-concern "Ignoring the law" 1)
                                           (make-concern "Science" 2)
                                           (make-concern "Keeping personal things secret" 1))))

;; Captain Nemo (by Jules Verne)
(define Nemo (make-person 'Nemo (list
                                 (make-concern "Adventures" 2)
                                 (make-concern "Ignoring the law" 2)
                                 (make-concern "Science" 1))))

;; Jack Griffin "The Invisible" (by Herbert George Wells)
(define Griffin (make-person 'JackGriffin (list
                                           (make-concern "Ignoring the law" 1)
                                           (make-concern "Science" 2)
                                           (make-concern "Keeping personal things secret" 1))))

;; Henry "Indiana" Jones Jr. (by George Lucas, Steven Spielberg)
(define Jones (make-person 'IndianaJones (list
                                          (make-concern "Hunting" 1)
                                          (make-concern "Treasure hunts" 2)
                                          (make-concern "Adventures" 2)
                                          (make-concern "Ignoring the law" -1)
                                          (make-concern "Occult things and rituals" 1)
                                          (make-concern "Science" -1)
                                          (make-concern "Keeping personal things secret" 2))))

;; Forever-alone
(define Forever-alone (make-person 'Forever-alone (list)))


;; League of extraordinary gentlemen
(define League (list Quatermain
                     Sawyer
                     Harker
                     Gray
                     Jekyll
                     Nemo
                     Griffin))

;; little League of extraordinary gentlemen
(define l-League (list Sawyer
                       Nemo
                       Griffin))

;; Forever-alone League
(define Fa-League (list Forever-alone))



;; 6.1
;; contract:    compare-concerns: concern concern -> number
;; description: Compares two concerns and gives back the absolute value of the difference, multiplied with two.
;; example:     (compare-concerns (make-concern "Hunting" 1) (make-concern "Hunting" -1)) -> 4

(define (compare-concerns concern1 concern2)
  (cond
    [(string=? (concern-topic concern1) (concern-topic concern2))
     (abs (* 2 (- (concern-value concern1) (concern-value concern2))))]
    [else
     (error 'compare-concerns "concern-topics are not identical")]))

;; Tests
(check-expect (compare-concerns (make-concern "Adventures" 2) (make-concern "Adventures" -1)) 6)
(check-error  (compare-concerns (make-concern "Science"   -1) (make-concern "Hunting"    -1)) "compare-concerns: concern-topics are not identical")



;; 6.2
;; contract:    compare-with-person: (listof concern) person -> number
;; description: Compares a single concern with all the concerns of a person.
;; example:     (compare-with-person (list (make-concern "Hunting" 1) (make-concern "Science" -2)) Nemo) -> 8

(define (compare-with-person concerns person)
  (cond
    [(empty? concerns) 0]
    [else
     (+ (find-concern (first concerns) (person-concerns person)) (compare-with-person (rest concerns) person))]))

;; Tests
(check-expect (compare-with-person (list (make-concern "Ignoring the law" -2) (make-concern "Science" 2) (make-concern "Hunting" 0)) Jekyll) 6)
(check-expect (compare-with-person (list (make-concern "Keeping personal things secret" 1) (make-concern "Occult things and rituals" -2)) Gray) 10)


;; auxiliary function
;; contract:    find-concern: concern (listof concerns) -> number
;; description: Searches the same concern-topic out of a list and compares the concerns.
;; example:     (find-concern (make-concern "Adventures" -1) (list (make-concern "Science" 1) (make-concern "Adventures" 2))) -> 6

(define (find-concern concern concerns)
  (cond
    [(empty? concerns) (abs (* 2 (concern-value concern)))]
    [(string=? (concern-topic concern) (concern-topic(first concerns))) (compare-concerns concern (first concerns))]
    [else (find-concern concern (rest concerns))]))

;; Tests
(check-expect (find-concern (first (person-concerns Jones))   (person-concerns Sawyer)) 2)
(check-expect (find-concern (third (person-concerns Griffin)) (person-concerns Harker)) 2)



;; 6.3
;; contract:    rate-league: (listof concern) (listof person) -> (listof person-similarity)
;; description: Compares the concerns of Indiana Jones with the concerns of people in a list and
;; gives back a list with the persons and the value of their overall antisimilarity.
;; example:     (rate-league (person-concerns Jones) l-League) -> (list (make-person-similarity 'TomSawyer 18)
;;                                                                      (make-person-similarity 'Nemo 22)
;;                                                                      (make-person-similarity 'JackGriffin 24))

(define (rate-league concerns persons)
  (cond
    [(empty? persons) empty]
    [else
     (cons (make-person-similarity (person-name (first persons)) (compare-with-person concerns (first persons))) (rate-league concerns (rest persons)))]))

;; Tests
(check-expect (rate-league (person-concerns Jones) Fa-League) (list (make-person-similarity 'Forever-alone 20)))

(check-expect (rate-league (person-concerns Jones) League)    (list (make-person-similarity 'AllanQuatermain 16) (make-person-similarity 'TomSawyer  18)
                                                                    (make-person-similarity 'MinaHarker      18) (make-person-similarity 'DorianGray 18)
                                                                    (make-person-similarity 'HenryJeckyll    24) (make-person-similarity 'Nemo       22)
                                                                    (make-person-similarity 'JackGriffin     24)))